package com.gwtjs.hbm2web.extjs;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import com.gwtjs.freemarker.FreemarkerManager;
import com.gwtjs.hbm2web.extjs.model.ExtJSApp;
import com.gwtjs.hbm2web.extjs.model.ExtJSItem;
import com.gwtjs.hbm2web.extjs.util.DataTypeJavaToExt;

import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * 生成dao的帮助工具 流操作应该提出来，参数的操作单独在此文件
 * 
 * @author aGuang
 * 
 */
public class Helper {

	private static Helper helper = new Helper();

	private Helper() {
	}

	public static Helper getInstance() {
		return helper;
	}
	
	private String getAppName(String pkg){
		pkg = pkg.substring(pkg.indexOf(".")+1);
		pkg = pkg.substring(0,pkg.indexOf("."));
		return pkg;
	}
	private String getClassName(String pkg){
		return pkg.substring(pkg.lastIndexOf(".")+1);
	}

	private String getClassRoot(Document doc) {
		Element root = doc.getRootElement();
		Element ele = root.element("class");
		String name = ele.attributeValue("name");
		//String table = ele.attributeValue("table");
		//String catalog = ele.attributeValue("catalog");
		//class: class : t_article : NewFrameworkTest
		//System.out.println("class: " + name + " : " + table + " : " + catalog);
		return name;
	}

	/**
	 * ID也是属性之一
	 * @param ele
	 * @return
	 */
	private ExtJSItem getClassId(Element ele) {
		ExtJSItem ei = new ExtJSItem();
		Node e = ele.selectSingleNode("//id");
		String type = DataTypeJavaToExt.getInstance().getExtDataType(e.valueOf("@type"));
		String length = e.valueOf("@length");
		//String column =  e.valueOf("@column");
		ei.setName("id"); // 如果主键名称不是id,呵呵.???
		ei.setType(type);
		ei.setLength(length);
		return ei;
	}

	private List<ExtJSItem> getHbmProperty(List<Element> nodes) {
		List<ExtJSItem> items = new ArrayList<ExtJSItem>();
		for (Element node : nodes) {
			ExtJSItem e = new ExtJSItem();
			e.setName(node.attributeValue("name"));
			String type = DataTypeJavaToExt.getInstance().getExtDataType(node.attributeValue("type"));
			e.setType(type);
			e.setLength(node.attributeValue("length"));
			items.add(e);
		}
		return items;
	}

	/**
	 * @param map
	 *            数据 基本数据加条目
	 * @param outPath
	 * @param templateName
	 */
	private void generateFile(Map<String, ExtJSApp> map, String outPath,
			String templateName) {
		File newPath = new File(outPath);
		// if(newPath.exists()){}
		Configuration cfg = FreemarkerManager.getconfiguration();
		try {
			Template temp = cfg.getTemplate(templateName);
			//temp.setEncoding("UTF-8");
			//System.out.println(temp.getEncoding());
			Writer out = new OutputStreamWriter(new FileOutputStream(newPath));
			temp.process(map, out);
			out.flush();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 将路径的"\"转换成"/"
	 */
	private String getPathName(String pkg) {
		StringBuffer rePkg = new StringBuffer();
		// 用SPOT转换数据
		StringTokenizer token = new StringTokenizer(pkg, "\\");
		while (token.hasMoreTokens()) {
			rePkg.append(token.nextToken());
			rePkg.append("/");
		}
		return rePkg.toString();
	}
	
	/**
	 * 建目录,每个模块有单独的目录
	 */
	private void mkdir(String path){
		File file = new File(path);
		if(!file.exists()){
			file.mkdirs();
		}
	}
	
	/**
	 * 生成入口
	 * 
	 * @param templatePath
	 *            模板路径
	 * @param outputPath
	 *            输出路径
	 *            <p>
	 *            这个方法应该重构一下，把参数改成实体的属性，并把此方法上提到CodeGenerator里面
	 *            </p>
	 * @throws IOException
	 */
	@SuppressWarnings("unchecked")
	public void generateJavaScript(String hbm, String outputPath) {
		String outName = getPathName(outputPath);
		
		String lowerName = "";
		String className = "";
		ExtJSApp app = new ExtJSApp();
		try {
			Document doc = new SAXReader().read(new File(hbm));// 读绝对路径的方法
			// Document doc = new
			// SAXReader().read(Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath));
			// //读相对类根目录的方法
			String pkg = this.getClassRoot(doc);
			String appName = getAppName(pkg);
			className = getClassName(pkg);
			lowerName = className.toLowerCase();
			app.setAppName(appName);
			app.setClassName(className);
			app.setLowerName(lowerName);
			Element root = doc.getRootElement();
			ExtJSItem ei = this.getClassId(root);
			List<ExtJSItem> items = this.getHbmProperty(doc.selectNodes("//class//property"));// xpath的读法，高效些
			items.add(ei);
			app.setItems(items);
			
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		Map<String, ExtJSApp> map = new HashMap<String, ExtJSApp>();
		map.put("app", app);
		
		String gridPath = outName+"view/"+lowerName+"/";
		String storePath = outName+"store/";
		String modelPath = outName+"model/";
		String formPath = outName+"form/";
		String windowPath = outName+"window/";
		
		this.mkdir(gridPath);
		this.mkdir(storePath);
		this.mkdir(modelPath);
		this.mkdir(formPath);
		this.mkdir(windowPath);
		
		System.out.println(modelPath+className+".js");
		generateFile(map, modelPath+className+".js", "model_template.ftl");
		System.out.println(formPath+className+"Form.js");
		generateFile(map, formPath+className+"Form.js", "form_template.ftl");
		System.out.println(windowPath+className+"Window.js");
		generateFile(map, windowPath+className+"Window.js", "window_template.ftl");
		System.out.println(storePath+className+"s.js");
		generateFile(map, storePath+className+"s.js", "store_template.ftl");
		System.out.println(gridPath+className+"Grid.js");
		generateFile(map, gridPath+className+"Grid.js", "grid_template.ftl");
	}
}
